/*
 * Ground.cpp
 *
 *  Created on: 15/06/2013
 *      Author: gabriel
 */

#include "Ground.h"

Ground::Ground(std::string filename, Shader *program) {

	this->filename = filename;
	this->shader = program;
	this->textureHandle = -1;
	this->vaoHandle = -1;

}

Ground::~Ground() {
}

void Ground::loadData(){

	this->colours = new float[16];
	this->vertices = new float[12];
	this->texCoord = new float [8];
	this->indices = new unsigned int[4];

	float squareVertices[] = {
			-1.0f, -1.0f, 0.0f ,
			1.0f, -1.0f, 0.0f ,
			1.0f,  1.0f, 0.0f ,
			-1.0f,  1.0f, 0.0f
	};

	float squareColours[] = {
			// Left half
			1.0f, 1.0f, 1.0f, 1.0f,
			1.0f, 1.0f, 1.0f, 1.0f,
			1.0f, 1.0f, 1.0f, 1.0f,
			1.0f, 1.0f, 1.0f, 1.0f
	};


	unsigned int index[] = {
			0,1,2,3
	};

	float tex_coord[] = {
			0.0f, 0.0f,  2.0f, 0.0f, 2.0f, 2.0f, 0.0f, 2.0f
	};


	for(int i = 0; i< 8; i++){
		texCoord[i] = tex_coord[i];
	}

	for (int i = 0; i < 4; i++) {
		indices[i] = index[i];
	}

	for (int i = 0; i < 12; i++) {
		vertices[i] = squareVertices[i];
	}

	for (int i = 0; i < 16; i++) {
		colours[i] = squareColours[i];
	}

}


void Ground::setup(){

	this->loadData();

	this->vaoHandle = createVAO();
	this->textureHandle = loadTexture(this->filename);


}

unsigned int Ground::createVAO(){

	unsigned int vaoHandle;
	glGenVertexArrays(1, &vaoHandle);
	glBindVertexArray(vaoHandle);

	int vertLoc = glGetAttribLocation(shader->programHandle, "a_vertex");
	int colourLoc = glGetAttribLocation(shader->programHandle, "a_colour_ambient");
	int texLoc = glGetAttribLocation(shader->programHandle, "a_tex_coord");

	// We get four buffers this time
	unsigned int buffer[4];
	glGenBuffers(4, buffer);

	// Set vertex attribute
	glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(float)*NUM_VERTICES*VALS_PER_VERT, vertices, GL_STATIC_DRAW);
	glEnableVertexAttribArray(vertLoc);
	glVertexAttribPointer(vertLoc, VALS_PER_VERT, GL_FLOAT, GL_FALSE, 0, 0);

	// Colour attributes
	glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(float)*NUM_VERTICES*VALS_PER_COLOUR, colours, GL_STATIC_DRAW);
	glEnableVertexAttribArray(colourLoc);
	glVertexAttribPointer(colourLoc, VALS_PER_COLOUR, GL_FLOAT, GL_FALSE, 0, 0);

	// Texture attributes
	glBindBuffer(GL_ARRAY_BUFFER, buffer[2]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(float)*NUM_SQUARES*VALS_PER_INDEX*VALS_PER_TEX, texCoord, GL_STATIC_DRAW);
	glEnableVertexAttribArray(texLoc);
	glVertexAttribPointer(texLoc, VALS_PER_TEX, GL_FLOAT, GL_FALSE, 0, 0);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[3]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*NUM_SQUARES*VALS_PER_INDEX, indices, GL_STATIC_DRAW);


	// Un-bind
	glBindVertexArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	return vaoHandle;
}


unsigned int Ground::loadTexture(std::string filename){

	TgaImage img(filename.c_str());

	glActiveTexture(GL_TEXTURE0);


	unsigned int textureHandle;
	glGenTextures(1, &textureHandle);

	glBindTexture(GL_TEXTURE_2D, textureHandle);


	glTexImage2D(	GL_TEXTURE_2D,
			0,
			img.dataType,
			img.imgWidth,
			img.imgHeight,
			0,
			img.format,
			GL_UNSIGNED_BYTE,
			img.imgData);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);



	return textureHandle;
}


void Ground::render(){

	glUseProgram(shader->programHandle);

	int textureUniformHandle = shader->getUniformHandle("texMap");
	int modelviewUniformHandle = shader->getUniformHandle("modelview_matrix");
	if (modelviewUniformHandle == -1 || textureUniformHandle == -1)
		exit(1);

	matrix.translate(0.0f, 0.0f, 0.0f);
	matrix.rotate(180.0f,1.0f,0.0f,0.0f );


	glBindVertexArray(vaoHandle);



	matrix.translate(0.0f, 1.0f, 0.0f);
	matrix.scale(50.0f, 0.0f, 50.0f);
	matrix.rotate(90.0f, 1.0f, 0.0f, 0.0f);

	glUniform1i(textureUniformHandle, 0);	// Note: '0' not 'GL_TEXTURE'
	glUniformMatrix4fv( modelviewUniformHandle, 1, false, matrix.m );
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, textureHandle);
	glDrawElements(GL_QUADS, NUM_SQUARES*VALS_PER_INDEX, GL_UNSIGNED_INT, 0);	// New call


	glBindTexture(GL_TEXTURE_2D, 0);
	glDisable(GL_TEXTURE_2D);
	glBindVertexArray(0);

}

void Ground::setMatrix(Matrix4f &matrix){
	this->matrix.copy(matrix);
}


